/*
 * The Open Source Unix Installer
 *
 * The MIT License
 *
 * Copyright 2011-2012 Andrey Pudov.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/*
 * @author  Andrey Pudov    <andrey@andreypudov.com>
 * @version 0.00.00
 * @name    dictionary.c
 * @date:   Feb 07, 2012
 */

#include "dictionary.h"

/* private code declaration */
static Dictionary* _installer_dictionary_search(Dictionary *dictionary, 
                                                const char *key);
static Dictionary* _installer_dictionary_insert(Dictionary **dictionary, 
                                                const char *key, 
                                                const wchar_t *value);

/* public code definition */
Dictionary* installer_dictionary_new() {
    return NULL;
}

void installer_dictionary_delete(Dictionary *dictionary) {
    if (dictionary != NULL) {
        installer_dictionary_delete(dictionary->left);
        installer_dictionary_delete(dictionary->right);

        if (dictionary->key != NULL) {
            free(dictionary->key);
        }

        if (dictionary->value != NULL) {
            free(dictionary->value);
        }

        free(dictionary); 
    }
}

wchar_t* installer_dictionary_get(Dictionary *dictionary, const char *key) {
                                  Dictionary *dictionary_ptr;

    /* class instance and key value are can't be NULL */
    if ((dictionary == NULL) || (key == NULL)) {
        return NULL;
    }

    /* store temporary value */
    dictionary_ptr = _installer_dictionary_search(dictionary, key);

    return (dictionary_ptr != NULL) ? dictionary_ptr->value : NULL;
}

Dictionary* installer_dictionary_set(Dictionary **dictionary, const char *key,
                                     const wchar_t *value) {

    /* class instance and key value are can't be NULL */
    if ((dictionary == NULL) || (key == NULL)) {
        return NULL;
    }

    return (_installer_dictionary_insert(dictionary, key, value));
}

/* private code definition */
Dictionary* _installer_dictionary_search(Dictionary *dictionary, 
                                         const char *key) {

    if (dictionary == NULL) {
        return NULL;
    }

    /* if dictionary->key is equal to key */
    if (strcmp(dictionary->key, key) == 0) {
        return dictionary;
    }

    /* if key is less than dictionary->key */
    if (strcmp(key, dictionary->key) < 0) {
        return (_installer_dictionary_search(dictionary->left, key));
    } else {
        return (_installer_dictionary_search(dictionary->right, key));
    }
}

Dictionary* _installer_dictionary_insert(Dictionary **dictionary, const char *key, 
                                  const wchar_t *value) {

    /* temporary pointer */
    Dictionary *dictionary_ptr;

    /* dictionary node is empty (first or last in the tree) */
    if (*dictionary == NULL) {
        /* allocate memmory to the new node */
        dictionary_ptr = (Dictionary*) malloc(sizeof(Dictionary));
        if (dictionary_ptr == NULL) {
    	    return NULL;
        }

        /* key should be not NULL, value can be NULL */
        dictionary_ptr->key = strdup(key);
        dictionary_ptr->value = (value != NULL) ? wcsdup(value) : NULL;

        dictionary_ptr->left = NULL;
        dictionary_ptr->right = NULL;

        /* the pointer  to the parent node */
        *dictionary = dictionary_ptr;

        return (*dictionary);
    }

    /* if key is less than (*dictionary)->key */
    int result = strcmp(key, (*dictionary)->key); 
    if (result < 0) {
        return (_installer_dictionary_insert(&((*dictionary)->left), key, value));
    } else if (result > 0) {
        return (_installer_dictionary_insert(&((*dictionary)->right), key, value));
    } else {
        free((*dictionary)->value);
        (*dictionary)->value = wcsdup(value);
        
        return (*dictionary);
    }
}
